#ifndef F64PLUSINTERFACE_H_
#define F64PLUSINTERFACE_H_

/*******************************************************************************
F64PlusInterface.h

===============================================================================
Copyright (c) 2010, Centeye, Inc.
All rights reserved.

Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
    * Redistributions of source code must retain the above copyright
      notice, this list of conditions and the following disclaimer.
    * Redistributions in binary form must reproduce the above copyright
      notice, this list of conditions and the following disclaimer in the
      documentation and/or other materials provided with the distribution.
    * Neither the name of Centeye, Inc. nor the
      names of its contributors may be used to endorse or promote products
      derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL CENTEYE, INC. BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
===============================================================================

Code to interface with Faraya64plus vision chip via the NAVio12B interface

This code interfaces with and performs basic operations on the Faraya64plus
vision chip. This code assumes that the NAVio12B port interface has been
established in AVR8sa1os1.

Origin:
Adapted from various AVR8 prototype libraries by Travis Young, for example
VCInterface and some from AtmelInterface.

Change Log:
2010 May 21, Friday, birth
2010 August 6, Friday, documentation

******************************************************************************/



//Default biases: These are the default biases for startup. Bias values may 
//range from 0 to 63 (6 bits), with "0" corresponding to the highest voltage
//and "63" corresponding to the lowest voltage. The exception is the PRSUPPLY
//bias, which is reversed so that "0" is lowest voltage and "63" highest
#define	NBIAS1_DEFAULT			56		
#define	VREF_DEFAULT			62		
#define	NBIAS2_DEFAULT			56	
#define	PRSUPPLY_DEFAULT		63				
#define	ANALOGOUTBIAS_DEFAULT	56
#define YUKNBIAS_DEFAULT		51
#define RESB_DEFAULT			63
#define REST_DEFAULT			0
	


//Vault keys: These are the commands to "open" and "close" the bias register vault
#define VCF64_CMD_KEY1					0x74C
#define VCF64_CMD_KEY1_INV				0x773
#define VCF64_CMD_KEY2					0x795
#define VCF64_CMD_KEY2_INV				0x7AA
#define VCF64_CMD_KEY3					0x7D6 
#define VCF64_CMD_KEY3_INV				0x7E9

//Defines of the command headers for the vision chip- these are the 12-bit command
//values with the "arguments" field (lower bits) cleared. Add the argument value
//to construct the whole 12-bit command. For example, to select row 8 the 
//resulting command code would be (CMD_ROWSEL + 8)
#define	VCF64_CMD_NBIAS1			0x000		
#define	VCF64_CMD_VREF				0x040		
#define	VCF64_CMD_NBIAS2			0x080		
#define	VCF64_CMD_PRSUPPLY			0x0C0		
#define	VCF64_CMD_ANALOGOUTBIAS		0x100
#define VCF64_CMD_YUKNBIAS			0x6C0
#define VCF64_CMD_RESB				0x640
#define VCF64_CMD_REST				0x680
#define VCF64_CMD_ROWSEL			0x800
#define VCF64_CMD_COLSEL			0x400
#define VCF64_CMD_VSW				0xC00
#define VCF64_CMD_HSW				0xA00
#define VCF64_CMD_AOEN				0xE00
#define VCF64_CMD_MISC				0x200
#define VCF64_CMD_MIDCONFIG			0x180
#define VCF64_CMD_MIDOP				0x1C0
#define VCF64_CMD_LREG1				0xE00
#define VCF64_CMD_LREG2				0xE40
#define VCF64_CMD_LREG3				0xE80
#define VCF64_CMD_LREG4				0xEC0
#define VCF64_CMD_ADCOP				0x600
#define VCF64_CMD_RESB				0x640
#define VCF64_CMD_REST				0x680
#define VCF64_CMD_MISC2				0x240
#define VCF64_CMD_MISC3				0x280
#define VCF64_CMD_CONNECTVDDA		0x702

// Sensor Commands: 1 Byte header to define one of 256 different commands
//
// The command headers are defined in different header files, depending on
// the function of the command. In general:
// Commands 0-29: reserved for operating system
// Commands 30-59: reserved for basic vision chip (biases etc.) operation
// Commands 60 and up: reserved for the application and defined here
//
// Below are commands 30-59 for the vision chip:
// NOTE: These are all KEYED: bit7=0, bit6=1
#define	COMM_CMD_NBIAS1					30		
#define	COMM_CMD_VREF					31		
#define	COMM_CMD_NBIAS2					32		
#define	COMM_CMD_PRSUPPLY				33		
#define	COMM_CMD_ANALOGOUTBIAS			34
#define COMM_CMD_ADCOP					35
#define COMM_CMD_RESB					36
#define COMM_CMD_REST					37
#define COMM_CMD_YUKNB					38
#define COMM_CMD_LREG1					39
#define COMM_CMD_LREG2					40
#define COMM_CMD_LREG3					41
#define COMM_CMD_LREG4					42
#define COMM_CMD_AMPTYPE				43		// Amplification type

// DATA SETS: Argument for "COMM_CMD_ATT" command to indicate what data
// set is set for transmit.
//
// The data sets are defined in different header files, depending on
// the function of the command. In general:
// Data sets 0-29: reserved for operating system
// Data set 30-59: reserved for basic vision chip operation
// Data set 60 and up: reserved for the application
//
// Below are data sets 30-59
#define	COMM_ATT_VC_BIASES				30

////////////////////////////////
// EEPROM VARIABLES
// These are the memory locations of the associated variables.
// The ATmega644P has 2kB EEPROM, so use addresses < 0x0800
// * 0x0000 is used in AVR8sa1os101.h
// For calibration values, each is 1 byte so use the top register to store the
// values, i.e. 0x0700 + the CMD number. They are defined in the respective
// files, this contains vision chip commands.
#define			EEP_VC_NBIAS1			( 0x0700 + COMM_CMD_NBIAS1 )
#define			EEP_VC_VREF				( 0x0700 + COMM_CMD_VREF )
#define			EEP_VC_NBIAS2			( 0x0700 + COMM_CMD_NBIAS2 )
#define			EEP_VC_PRSUPPLY			( 0x0700 + COMM_CMD_PRSUPPLY )
#define			EEP_VC_ANALOGOUTBIAS	( 0x0700 + COMM_CMD_ANALOGOUTBIAS )
#define			EEP_VC_RESB				( 0x0700 + COMM_CMD_RESB )
#define			EEP_VC_REST				( 0x0700 + COMM_CMD_REST )
#define			EEP_VC_YUKNB			( 0x0700 + COMM_CMD_YUKNB )
#define			EEP_VC_AMPTYPE			( 0x0700 + COMM_CMD_AMPTYPE )

//biases structure
struct	Biases
{
	unsigned char	UpdateReq;			// update required flag
	/* The following values are retained for readability of code,
	 * but they now point to values in the BiasSettingATT.read array
	 * so the values can be queried by the host computer.
	 */
	unsigned char	*NBias1;
	unsigned char	*VREF;
	unsigned char	*NBias2;
	unsigned char	*PRSupply;
	unsigned char	*AnalogOutBias;
	unsigned char 	*YukNBias;
	unsigned char	*ResB;
	unsigned char	*ResT;
} BiasSettings;

struct {
	unsigned char locked;	// 1 = locked, 0 = unlocked
	unsigned char read_length;
	// read array values:
	// NBias1, VREF, NBias2, PRSupply, AnalogOutBias,
	// YukNBias, ResB, ResT, Amp_Type
	unsigned char read[9];
} BiasSettingsATT;

void process_F64_command(unsigned char cmd0, unsigned char cmd1);
void process_F64_transmit(unsigned char array_to_transmit);

unsigned char		*Amp_Type;						// method of amplification

//setup functions
void 				open_vault(void);
void 				close_vault(void);
void				init_biases(void);
void 				VC_init(void);

//functions to operate the VC
void 				send_command(short int data);
void 				set_biases(void);
void				load_caps(void);
void				amplify(void);
void 				smooth_image(int row,int col);




//////////////////////////////////////////////////////////////////////////////
// DELAY1: MACRO to cause a simple delay
//////////////////////////////////////////////////////////////////////////////
#define Delay1(loop) \
{ \
	int i; \
	for(i=0;i<loop;i++) \
	{ \
	asm("	NOP"); \
	asm("	NOP"); \
	asm("	NOP"); \
	asm("	NOP"); \
	asm("	NOP"); \
	} \
}

//////////////////////////////////////////////////////////////////////////////
// LOADHEADER: MACRO to load the upper 6 bits of a command to the NAVio12B
// interface via the IO0..IO7 lines. When the upper six bits are loaded, 
// they are stored on the chip for later use. No command is executed until
// the lower six bits are uploaded.
//////////////////////////////////////////////////////////////////////////////
#define LoadHeader(header) \
{ \
	PORTB|=PB_WNR; \
	PORTD|=PD_IO7_HILO; \
	PORTD&=PD_IO_0_5_INV; \
	PORTD|= (header & 0x3F); \
	PORTB|=PB_CS1; \
	Delay1(1); \
	PORTB&=PB_CS1_INV; \
}

//////////////////////////////////////////////////////////////////////////////
// LOADDATA: MACRO to load the lower 6 bits of a command to the NAVio12B 
// interface via the IO0..IO7 lines. When the lower six bits are loaded, the
// chip will execute the command formed by these lower six bits and the
// previously loaded upper six bits.
//////////////////////////////////////////////////////////////////////////////
#define LoadData(data) \
{ \
	PORTB|=PB_WNR; \
	PORTD&=PD_IO7_HILO_INV; \
	PORTD&=PD_IO_0_5_INV; \
	PORTD|= (data & 0x3F); \
	PORTB|=PB_CS1; \
	Delay1(1); \
	PORTB&=PB_CS1_INV; \
}

//////////////////////////////////////////////////////////////////////////////
// LOADCMD: MACRO to load an entire 12-bit command to NAVio12B
//////////////////////////////////////////////////////////////////////////////
#define LoadCmd(cmd) \
{ \
	LoadHeader(((cmd&0xFC0)>>6)); \
	LoadData((cmd&0x03F)); \
}

//////////////////////////////////////////////////////////////////////////////
// GETPIXADC: MACRO to read a single pixel of column c from the vision chip
// using the on-chip 8-bit ADC. The result is read from the NAVio12 IO lines.
//////////////////////////////////////////////////////////////////////////////
#define GetPixADC(PixVal,c) \
{ \
	LoadCmd((VCF64_CMD_COLSEL+c)); \
	LoadCmd((VCF64_CMD_ADCOP+0x02)); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	asm("\tNOP"); \
	LoadCmd((VCF64_CMD_ADCOP+0x03)); \
	DDRD=0x00; \
	PORTB&=PB_WNR_INV; \
	PORTB|=PB_CS1; \
	Delay1(1); \
	PixVal=PIND; \
	PORTB&=PB_CS1_INV; \
	PORTB|=PB_WNR; \
	DDRD=0xFF; \
	LoadCmd((VCF64_CMD_ADCOP+0x02)); \
} \


//////////////////////////////////////////////////////////////////////////////
// GETPIXAVRADC: MACRO to read a single pixel of column c from the vision chip
// using the AVR's ADC. This macro has not yet been written.
//////////////////////////////////////////////////////////////////////////////


#endif /*F64PLUSINTERFACE_H_*/
